home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / drivers / polyplay.c < prev    next >
C/C++ Source or Header  |  2000-04-22  |  13KB  |  436 lines

  1. /***************************************************************************
  2.  
  3.       Poly-Play
  4.       (c) 1985 by VEB Polytechnik Karl-Marx-Stadt
  5.  
  6.       driver by Martin Buchholz (buchholz@mail.uni-greifswald.de)
  7.  
  8.       Very special thanks to the following people, each one of them spent
  9.       some of their spare time to make this driver working:
  10.       - Juergen Oppermann and Volker Hann for electronical assistance,
  11.         repair work and ROM dumping.
  12.       - Jan-Ole Christian from the Videogamemuseum in Berlin, which houses
  13.         one of the last existing Poly-Play arcade automatons. He also
  14.         provided me with schematics and service manuals.
  15.  
  16.  
  17. memory map:
  18.  
  19. 0000 - 03ff OS ROM
  20. 0400 - 07ff Game ROM (used for Abfahrtslauf)
  21. 0800 - 0cff Menu Screen ROM
  22.  
  23. 0d00 - 0fff work RAM
  24.  
  25. 1000 - 4fff GAME ROM (pcb 2 - Abfahrtslauf          (1000 - 1bff),
  26.                               Hirschjagd            (1c00 - 27ff),
  27.                               Hase und Wolf         (2800 - 3fff),
  28.                               Schmetterlingsfang    (4000 - 4fff)
  29. 5000 - 8fff GAME ROM (pcb 1 - Schiessbude           (5000 - 5fff)
  30.                               Autorennen            (6000 - 73ff)
  31.                               opto-akust. Merkspiel (7400 - 7fff)
  32.                               Wasserrohrbruch       (8000 - 8fff)
  33.  
  34. e800 - ebff character ROM (chr 00..7f) 1 bit per pixel
  35. ec00 - f7ff character RAM (chr 80..ff) 3 bit per pixel
  36. f800 - ffff video RAM
  37.  
  38. I/O ports:
  39.  
  40. read:
  41.  
  42. 83        IN1
  43.           used as hardware random number generator
  44.  
  45. 84        IN0
  46.           bit 0 = fire button
  47.           bit 1 = right
  48.           bit 2 = left
  49.           bit 3 = up
  50.           bit 4 = down
  51.           bit 5 = unused
  52.           bit 6 = Summe Spiele
  53.           bit 7 = coinage (+IRQ to make the game acknowledge it)
  54.  
  55. 85        bit 0-4 = light organ (unemulated :)) )
  56.           bit 5-7 = sound parameter (unemulated, it's very difficult to
  57.                     figure out how those work)
  58.  
  59. 86        ???
  60.  
  61. 87        PIO Control register
  62.  
  63. write:
  64. 80          Sound Channel 1
  65. 81        Sound Channel 2
  66. 82        generates 40 Hz timer for timeout in game title screens
  67. 83        generates main 75 Hz timer interrupt
  68.  
  69. The Poly-Play has a simple bookmarking system which can be activated
  70. setting Bit 6 of PORTA (Summe Spiele) to low. It reads a double word
  71. from 0c00 and displays it on the screen.
  72. I currently haven't figured out how the I/O port handling for the book-
  73. mark system works.
  74.  
  75. Uniquely the Poly-Play has a light organ which totally confuses you whilst
  76. playing the automaton. Bits 1-5 of PORTB control the organ but it's not
  77. emulated now. ;)
  78.  
  79. ***************************************************************************/
  80.  
  81. #include "driver.h"
  82. #include "vidhrdw/generic.h"
  83. #include "cpu/z80/z80.h"
  84.  
  85. static unsigned char *polyplay_ram;
  86.  
  87. void polyplay_reset(void);
  88.  
  89. /* video hardware access */
  90. extern unsigned char *polyplay_characterram;
  91. void polyplay_init_palette(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom);
  92. void polyplay_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);
  93. READ_HANDLER( polyplay_characterram_r );
  94. WRITE_HANDLER( polyplay_characterram_w );
  95.  
  96. /* I/O Port handling */
  97. READ_HANDLER( polyplay_input_read );
  98. READ_HANDLER( polyplay_random_read );
  99.  
  100. /* sound handling */
  101. void poly_sound(void);
  102. void set_channel1(int active);
  103. void set_channel2(int active);
  104. int prescale1, prescale2;
  105. static int channel1_active;
  106. static int channel1_const;
  107. static int channel2_active;
  108. static int channel2_const;
  109. static void init_polyplay_sound(void);
  110. void play_channel1(int data);
  111. void play_channel2(int data);
  112. int  polyplay_sh_start(const struct MachineSound *msound);
  113. void polyplay_sh_stop(void);
  114. void polyplay_sh_update(void);
  115.  
  116. /* timer handling */
  117. static void polyplay_timer(int param);
  118. int timer2_active;
  119. WRITE_HANDLER( polyplay_start_timer2 );
  120. WRITE_HANDLER( polyplay_sound_channel );
  121.  
  122.  
  123. /* Polyplay Sound Interface */
  124. static struct CustomSound_interface custom_interface =
  125. {
  126.     polyplay_sh_start,
  127.     polyplay_sh_stop,
  128.     polyplay_sh_update
  129. };
  130.  
  131.  
  132. void polyplay_reset(void)
  133. {
  134.     channel1_active = 0;
  135.     channel1_const = 0;
  136.     channel2_active = 0;
  137.     channel2_const = 0;
  138.     set_channel1(0);
  139.     play_channel1(0);
  140.     set_channel2(0);
  141.     play_channel2(0);
  142. }
  143.  
  144.  
  145. /* work RAM access */
  146. WRITE_HANDLER( polyplay_ram_w )
  147. {
  148.     polyplay_ram[offset] = data;
  149. }
  150.  
  151. READ_HANDLER( polyplay_ram_r )
  152. {
  153.     return polyplay_ram[offset];
  154. }
  155.  
  156. /* memory mapping */
  157. static struct MemoryReadAddress polyplay_readmem[] =
  158. {
  159.     { 0x0000, 0x0bff, MRA_ROM },
  160.     { 0x0c00, 0x0fff, polyplay_ram_r },
  161.     { 0x1000, 0x8fff, MRA_ROM },
  162.  
  163.     { 0xe800, 0xebff, MRA_ROM},
  164.     { 0xec00, 0xf7ff, polyplay_characterram_r },
  165.     { 0xf800, 0xffff, videoram_r },
  166.     { -1 }  /* end of table */
  167. };
  168.  
  169. static struct MemoryWriteAddress polyplay_writemem[] =
  170. {
  171.     { 0x0000, 0x0bff, MWA_ROM },
  172.     { 0x0c00, 0x0fff, polyplay_ram_w, &polyplay_ram },
  173.     { 0x1000, 0x8fff, MWA_ROM },
  174.  
  175.     { 0xe800, 0xebff, MWA_ROM },
  176.     { 0xec00, 0xf7ff, polyplay_characterram_w, &polyplay_characterram },
  177.     { 0xf800, 0xffff, videoram_w, &videoram, &videoram_size },
  178.     { -1 }  /* end of table */
  179. };
  180.  
  181.  
  182. /* port mapping */
  183. static struct IOReadPort readport_polyplay[] =
  184. {
  185.     { 0x84, 0x84, polyplay_input_read },
  186.     { 0x83, 0x83, polyplay_random_read },
  187.     { -1 }  /* end of table */
  188. };
  189.  
  190. static struct IOWritePort writeport_polyplay[] =
  191. {    { 0x80, 0x81, polyplay_sound_channel },
  192.     { 0x82, 0x82, polyplay_start_timer2 },
  193.     { -1 }  /* end of table */
  194. };
  195.  
  196. INPUT_PORTS_START( polyplay )
  197.     PORT_START    /* IN0 */
  198.     PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
  199.     PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_8WAY )
  200.     PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT  | IPF_8WAY )
  201.     PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP    | IPF_8WAY )
  202.     PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN  | IPF_8WAY )
  203.     PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
  204.     PORT_BITX(0x40, IP_ACTIVE_LOW, IPT_SERVICE, "Bookkeeping Info", KEYCODE_F2, IP_JOY_NONE )
  205.     PORT_BIT_IMPULSE( 0x80, IP_ACTIVE_LOW, IPT_COIN1, 10)
  206. INPUT_PORTS_END
  207.  
  208.  
  209. WRITE_HANDLER( polyplay_sound_channel )
  210. {
  211.     switch(offset) {
  212.     case 0x00:
  213.         if (channel1_const) {
  214.             if (data <= 1) {
  215.                 set_channel1(0);
  216.             }
  217.             channel1_const = 0;
  218.             play_channel1(data*prescale1);
  219.  
  220.         }
  221.         else {
  222.             prescale1 = (data & 0x20) ? 16 : 1;
  223.             if (data & 0x04) {
  224.                 set_channel1(1);
  225.                 channel1_const = 1;
  226.             }
  227.             if ((data == 0x41) || (data == 0x65) || (data == 0x45)) {
  228.                 set_channel1(0);
  229.                 play_channel1(0);
  230.             }
  231.         }
  232.         break;
  233.     case 0x01:
  234.         if (channel2_const) {
  235.             if (data <= 1) {
  236.                 set_channel2(0);
  237.             }
  238.             channel2_const = 0;
  239.             play_channel2(data*prescale2);
  240.  
  241.         }
  242.         else {
  243.             prescale2 = (data & 0x20) ? 16 : 1;
  244.             if (data & 0x04) {
  245.                 set_channel2(1);
  246.                 channel2_const = 1;
  247.             }
  248.             if ((data == 0x41) || (data == 0x65) || (data == 0x45)) {
  249.                 set_channel2(0);
  250.                 play_channel2(0);
  251.             }
  252.         }
  253.         break;
  254.     }
  255. }
  256.  
  257. WRITE_HANDLER( polyplay_start_timer2 )
  258. {
  259.     if (data == 0x03) {
  260.         timer2_active = 0;
  261.     }
  262.     else {
  263.         if (data == 0xb5) {
  264.             timer_set(TIME_IN_HZ(40), 1, polyplay_timer);
  265.             timer2_active = 1;
  266.         }
  267.     }
  268. }
  269.  
  270. /* random number generator */
  271. READ_HANDLER( polyplay_random_read )
  272. {
  273.     return rand() % 0xff;
  274. }
  275.  
  276. /* graphic sturctures */
  277. static struct GfxLayout charlayout_1_bit =
  278. {
  279.     8,8,    /* 8*8 characters */
  280.     128,    /* 128 characters */
  281.     1,        /* 1 bit per pixel */
  282.     { 0 },
  283.     { 0, 1, 2, 3, 4, 5, 6, 7 },    /* pretty straightforward layout */
  284.     { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
  285.     8*8    /* every char takes 8 consecutive bytes */
  286. };
  287.  
  288. static struct GfxLayout charlayout_3_bit =
  289. {
  290.     8,8,    /* 8*8 characters */
  291.     128,    /* 128 characters */
  292.     3,        /* 3 bit per pixel */
  293.     { 0, 128*8*8, 128*8*8 + 128*8*8 },    /* offset for each bitplane */
  294.     { 0, 1, 2, 3, 4, 5, 6, 7 },    /* pretty straightforward layout */
  295.     { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
  296.     8*8    /* every char takes 8 consecutive bytes */
  297. };
  298.  
  299. static struct GfxDecodeInfo gfxdecodeinfo[] =
  300. {
  301.     { 0, 0xe800, &charlayout_1_bit, 0, 2 },
  302.     { 0, 0xec00, &charlayout_3_bit, 2, 8 },
  303.     { -1 }    /* end of array */
  304. };
  305.  
  306.  
  307. /* the machine driver */
  308.  
  309. #define MACHINEDRIVER(NAME, MEM, PORT)                \
  310. static struct MachineDriver machine_driver_##NAME =    \
  311. {                                                    \
  312.     /* basic machine hardware */                    \
  313.     {                                                \
  314.         {                                            \
  315.             CPU_Z80,                                \
  316.             9830400/4,                                \
  317.             MEM##_readmem,MEM##_writemem,           \
  318.             readport_##PORT,writeport_polyplay,        \
  319.             ignore_interrupt, 1                    \
  320.         }                                            \
  321.     },                                                \
  322.     50, 0,    /* frames per second, vblank duration */ \
  323.     0,    /* single CPU, no need for interleaving */    \
  324.     polyplay_reset,                                    \
  325.                                                     \
  326.     /* video hardware */                            \
  327.     64*8, 32*8, { 0*8, 64*8-1, 0*8, 32*8-1 },        \
  328.     gfxdecodeinfo,                                    \
  329.     64, 64,                                            \
  330.     polyplay_init_palette,                            \
  331.                                                     \
  332.     VIDEO_TYPE_RASTER|VIDEO_SUPPORTS_DIRTY,            \
  333.     0,                                                \
  334.     generic_vh_start,                                \
  335.     generic_vh_stop,                                \
  336.     polyplay_vh_screenrefresh,                        \
  337.                                                     \
  338.     /* sound hardware */                            \
  339.     0,0,0,0,                                            \
  340.     {                                                \
  341.         {                                            \
  342.             SOUND_CUSTOM,                            \
  343.             &custom_interface                        \
  344.         }                                            \
  345.     }                                                \
  346. };
  347.  
  348. MACHINEDRIVER( polyplay, polyplay, polyplay )
  349.  
  350.  
  351.  
  352. /* ROM loading and mapping */
  353. ROM_START( polyplay )
  354.     ROM_REGION( 0x10000, REGION_CPU1 )    /* 64k for code */
  355.     ROM_LOAD( "cpu_0000.37",       0x0000, 0x0400, 0x87884c5f )
  356.     ROM_LOAD( "cpu_0400.36",       0x0400, 0x0400, 0xd5c84829 )
  357.     ROM_LOAD( "cpu_0800.35",       0x0800, 0x0400, 0x5f36d08e )
  358.     ROM_LOAD( "2_-_1000.14",       0x1000, 0x0400, 0x950dfcdb )
  359.     ROM_LOAD( "2_-_1400.10",       0x1400, 0x0400, 0x829f74ca )
  360.     ROM_LOAD( "2_-_1800.6",        0x1800, 0x0400, 0xb69306f5 )
  361.     ROM_LOAD( "2_-_1c00.2",        0x1c00, 0x0400, 0xaede2280 )
  362.     ROM_LOAD( "2_-_2000.15",       0x2000, 0x0400, 0x6c7ad0d8 )
  363.     ROM_LOAD( "2_-_2400.11",       0x2400, 0x0400, 0xbc7462f0 )
  364.     ROM_LOAD( "2_-_2800.7",        0x2800, 0x0400, 0x9ccf1958 )
  365.     ROM_LOAD( "2_-_2c00.3",        0x2c00, 0x0400, 0x21827930 )
  366.     ROM_LOAD( "2_-_3000.16",       0x3000, 0x0400, 0xb3b3c0ec )
  367.     ROM_LOAD( "2_-_3400.12",       0x3400, 0x0400, 0xbd416cd0 )
  368.     ROM_LOAD( "2_-_3800.8",        0x3800, 0x0400, 0x1c470b7c )
  369.     ROM_LOAD( "2_-_3c00.4",        0x3c00, 0x0400, 0xb8354a19 )
  370.     ROM_LOAD( "2_-_4000.17",       0x4000, 0x0400, 0x1e01041e )
  371.     ROM_LOAD( "2_-_4400.13",       0x4400, 0x0400, 0xfe4d8959 )
  372.     ROM_LOAD( "2_-_4800.9",        0x4800, 0x0400, 0xc45f1d9d )
  373.     ROM_LOAD( "2_-_4c00.5",        0x4c00, 0x0400, 0x26950ad6 )
  374.     ROM_LOAD( "1_-_5000.30",       0x5000, 0x0400, 0x9f5e2ba1 )
  375.     ROM_LOAD( "1_-_5400.26",       0x5400, 0x0400, 0xb5f9a780 )
  376.     ROM_LOAD( "1_-_5800.22",       0x5800, 0x0400, 0xd973ad12 )
  377.     ROM_LOAD( "1_-_5c00.18",       0x5c00, 0x0400, 0x9c22ea79 )
  378.     ROM_LOAD( "1_-_6000.31",       0x6000, 0x0400, 0x245c49ca )
  379.     ROM_LOAD( "1_-_6400.27",       0x6400, 0x0400, 0x181e427e )
  380.     ROM_LOAD( "1_-_6800.23",       0x6800, 0x0400, 0x8a6c1f97 )
  381.     ROM_LOAD( "1_-_6c00.19",       0x6c00, 0x0400, 0x77901dc9 )
  382.     ROM_LOAD( "1_-_7000.32",       0x7000, 0x0400, 0x83ffbe57 )
  383.     ROM_LOAD( "1_-_7400.28",       0x7400, 0x0400, 0xe2a66531 )
  384.     ROM_LOAD( "1_-_7800.24",       0x7800, 0x0400, 0x1d0803ef )
  385.     ROM_LOAD( "1_-_7c00.20",       0x7c00, 0x0400, 0x17dfa7e4 )
  386.     ROM_LOAD( "1_-_8000.33",       0x8000, 0x0400, 0x6ee02375 )
  387.     ROM_LOAD( "1_-_8400.29",       0x8400, 0x0400, 0x9db09598 )
  388.     ROM_LOAD( "1_-_8800.25",       0x8800, 0x0400, 0xca2f963f )
  389.     ROM_LOAD( "1_-_8c00.21",       0x8c00, 0x0400, 0x0c7dec2d )
  390.     ROM_LOAD( "char.1",            0xe800, 0x0400, 0x5242dd6b )
  391. ROM_END
  392.  
  393.  
  394. /* interrupt handling, the game runs in IM 2 */
  395. READ_HANDLER( polyplay_input_read )
  396. {
  397.     int inp = input_port_0_r(offset);
  398.  
  399.     if ((inp & 0x80) == 0) {    /* Coin inserted */
  400.         cpu_cause_interrupt(0, 0x50);
  401.         coin_counter_w(0, 1);
  402.         timer_set(TIME_IN_SEC(1), 2, polyplay_timer);
  403.     }
  404.  
  405.     return inp;
  406. }
  407.  
  408. static void polyplay_timer(int param)
  409. {
  410.     switch(param) {
  411.     case 0:
  412.         cpu_cause_interrupt(0, 0x4e);
  413.         break;
  414.     case 1:
  415.         if (timer2_active) {
  416.             timer_set(TIME_IN_HZ(40), 1, polyplay_timer);
  417.             cpu_cause_interrupt(0, 0x4c);
  418.         }
  419.         break;
  420.     case 2:
  421.         coin_counter_w(0, 0);
  422.         break;
  423.     }
  424. }
  425.  
  426. /* initialization */
  427. static void init_polyplay_sound(void)
  428. {
  429.     timer_init();
  430.     timer_pulse(TIME_IN_HZ(75), 0, polyplay_timer);
  431.     timer2_active = 0;
  432. }
  433.  
  434. /* game driver */
  435. GAME( 1985, polyplay, 0, polyplay, polyplay, polyplay_sound, ROT0, "VEB Polytechnik Karl-Marx-Stadt", "Poly-Play" )
  436.